import os
# 在导入matplotlib之前设置非交互式后端
import matplotlib

matplotlib.use('Agg')  # 使用Agg后端，适用于生成图像文件而不需要交互式显示

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties, findfont, FontManager
import numpy as np
import mplfinance as mpf
from datetime import datetime

# 设置文件路径
file_path = 'd:\\1\\比亚迪后复权历史行情数据.xlsx'

# 设置matplotlib全局字体支持中文
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC', 'Arial Unicode MS']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

# 检查文件是否存在
if not os.path.exists(file_path):
    print(f"文件不存在: {file_path}")
    exit()

# 读取Excel文件
try:
    # 使用pandas读取Excel文件
    df = pd.read_excel(file_path)

    # 显示数据基本信息
    print("文件读取成功！")
    print(f"\n数据形状: {df.shape}")
    print(f"\n列名: {list(df.columns)}")
    print(f"\n数据类型:")
    print(df.dtypes)

    # 显示前5行数据（根据要求）
    print(f"\n前5行数据:")
    print(df.head())

    # 详细的变量描述性分析
    print(f"\n=== 变量描述性分析 ===")

    # 1. 数值型变量的统计描述
    print("\n1. 数值型变量统计描述:")
    numeric_cols = df.select_dtypes(include=['float64', 'int64']).columns
    if len(numeric_cols) > 0:
        print(f"\n数值型列: {list(numeric_cols)}")
        print("\n基本统计量:")
        print(df[numeric_cols].describe())

        # 额外的统计信息
        print("\n额外统计信息:")
        print("偏度(Skewness):")
        print(df[numeric_cols].skew())
        print("\n峰度(Kurtosis):")
        print(df[numeric_cols].kurtosis())
        print("\n中位数:")
        print(df[numeric_cols].median())

        # 计算相关系数矩阵
        print("\n=== 相关系数分析 ===")
        corr_matrix = df[numeric_cols].corr()
        print("\n相关系数矩阵:")
        print(corr_matrix)

        # 识别高度相关的变量对（相关系数绝对值大于0.7）
        print("\n高度相关的变量对（相关系数绝对值 > 0.7）:")
        high_corr = []
        for i in range(len(corr_matrix.columns)):
            for j in range(i):
                if abs(corr_matrix.iloc[i, j]) > 0.7:
                    high_corr.append((corr_matrix.columns[i], corr_matrix.columns[j], corr_matrix.iloc[i, j]))

        if high_corr:
            for var1, var2, corr in high_corr:
                print(f"{var1} 和 {var2}: {corr:.4f}")
        else:
            print("未发现高度相关的变量对")

        # 绘制相关系数热力图
        print("\n绘制相关系数热力图...")
        plt.figure(figsize=(12, 10))

        # 设置中文字体支持
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
        plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

        # 绘制热力图
        heatmap = sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5,
                              vmin=-1, vmax=1, square=True, cbar_kws={'label': '相关系数'})

        # 设置标题和标签
        plt.title('比亚迪股票数据变量相关系数热力图', fontsize=16, pad=20)
        plt.tight_layout()

        # 保存热力图
        heatmap_path = 'd:\\1\\correlation_heatmap.png'
        plt.savefig(heatmap_path, dpi=300, bbox_inches='tight')
        plt.close()
        print(f"\n热力图已保存至: {heatmap_path}")

    else:
        print("未发现数值型变量，无法计算相关系数")

    # 2. 非数值型变量的描述
    print("\n2. 非数值型变量描述:")
    non_numeric_cols = df.select_dtypes(exclude=['float64', 'int64']).columns
    if len(non_numeric_cols) > 0:
        print(f"\n非数值型列: {list(non_numeric_cols)}")
        print("\n非数值型变量信息:")
        print(df[non_numeric_cols].describe())

        # 检查每列的唯一值数量
        print("\n每列唯一值数量:")
        for col in non_numeric_cols:
            print(f"{col}: {df[col].nunique()} 个唯一值")
    else:
        print("未发现非数值型变量")

    # 3. 缺失值分析
    print("\n3. 缺失值分析:")
    missing_data = df.isnull().sum()
    if missing_data.sum() > 0:
        print("存在缺失值的列:")
        print(missing_data[missing_data > 0])
        print(f"\n总缺失值数量: {missing_data.sum()}")
        print(f"缺失值比例: {(missing_data.sum() / (df.shape[0] * df.shape[1])) * 100:.2f}%")
    else:
        print("没有缺失值")

    # 4. 数据量分析
    print("\n4. 数据量分析:")
    print(f"总记录数: {df.shape[0]}")
    print(f"总变量数: {df.shape[1]}")
    print(f"数据密度: {(df.shape[0] * df.shape[1]) / (df.shape[0] * df.shape[1]) * 100:.2f}%")

    # 绘制2023年收盘价时序图
    print("\n=== 绘制2023年收盘价时序图 ===")

    # 确保日期列转换为datetime类型
    if '日期' in df.columns:
        df['日期'] = pd.to_datetime(df['日期'])
        print(f"\n日期范围: {df['日期'].min()} 至 {df['日期'].max()}")

        # 检查是否包含收盘价列
        close_col = None
        volume_col = None
        for col in df.columns:
            if '收盘' in str(col):
                close_col = col
            elif '成交量' in str(col):
                volume_col = col

        if close_col:
            print(f"\n使用收盘价列: {close_col}")

            # 创建时序图
            plt.figure(figsize=(14, 7))

            # 设置中文字体支持
            plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
            plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

            # 绘制收盘价时间序列
            plt.plot(df['日期'], df[close_col], 'b-', linewidth=2, label='收盘价')

            # 计算并绘制移动平均线（可选，用于显示趋势）
            df['MA20'] = df[close_col].rolling(window=20).mean()
            df['MA60'] = df[close_col].rolling(window=60).mean()
            plt.plot(df['日期'], df['MA20'], 'r--', linewidth=1.5, label='20日均线')
            plt.plot(df['日期'], df['MA60'], 'g-.', linewidth=1.5, label='60日均线')

            # 设置标题和标签
            plt.title('2023年比亚迪股票收盘价时序图', fontsize=16, pad=20)
            plt.xlabel('日期', fontsize=12, labelpad=10)
            plt.ylabel('收盘价', fontsize=12, labelpad=10)

            # 设置网格线
            plt.grid(True, linestyle='--', alpha=0.7)

            # 添加图例
            plt.legend(fontsize=10)

            # 自动调整日期标签角度
            plt.xticks(rotation=45)
            plt.tight_layout()

            # 保存时序图
            timeseries_path = 'd:\\1\\byd_close_price_timeseries.png'
            plt.savefig(timeseries_path, dpi=300, bbox_inches='tight')
            plt.close()
            print(f"\n收盘价时序图已保存至: {timeseries_path}")

            # 计算一些基本的时序统计信息
            print("\n收盘价时序统计:")
            print(f"年度最高收盘价: {df[close_col].max():.2f}")
            print(f"年度最低收盘价: {df[close_col].min():.2f}")
            print(f"年度平均收盘价: {df[close_col].mean():.2f}")
            print(f"年初收盘价: {df.iloc[0][close_col]:.2f}")
            print(f"年末收盘价: {df.iloc[-1][close_col]:.2f}")

            # 计算年度涨跌幅
            annual_return = (df.iloc[-1][close_col] - df.iloc[0][close_col]) / df.iloc[0][close_col] * 100
            print(f"年度涨跌幅: {annual_return:.2f}%")
        # 绘制成交量柱状图
        print("\n=== 绘制成交量柱状图 ===")
        if volume_col:
            plt.figure(figsize=(14, 7))

            # 绘制成交量柱状图
            plt.bar(df['日期'], df[volume_col], color='orange', alpha=0.7, label='成交量')

            # 计算并绘制成交量30日均线
            df['Volume_MA30'] = df[volume_col].rolling(window=30).mean()
            plt.plot(df['日期'], df['Volume_MA30'], 'blue', linewidth=2, label='成交量30日均线')

            # 设置标题和标签
            plt.title('2023年比亚迪股票成交量趋势', fontsize=16, pad=20)
            plt.xlabel('日期', fontsize=12, labelpad=10)
            plt.ylabel('成交量', fontsize=12, labelpad=10)

            # 设置网格线
            plt.grid(True, linestyle='--', alpha=0.3, axis='y')

            # 添加图例
            plt.legend(fontsize=10)

            # 自动调整日期标签角度
            plt.xticks(rotation=45)
            plt.tight_layout()

            # 保存成交量柱状图
            volume_path = 'd:\\1\\byd_volume_trend.png'
            plt.savefig(volume_path, dpi=300, bbox_inches='tight')
            plt.close()
            print(f"\n成交量柱状图已保存至: {volume_path}")

            # 成交量统计
            print("\n成交量统计:")
            print(f"平均成交量: {df[volume_col].mean():.0f}")
            print(f"最大成交量: {df[volume_col].max():.0f} (日期: {df.loc[df[volume_col].idxmax(), '日期']})")
            print(f"最小成交量: {df[volume_col].min():.0f} (日期: {df.loc[df[volume_col].idxmin(), '日期']})")

        # 绘制涨跌幅分布图
        print("\n=== 绘制涨跌幅分布图 ===")
        # 查找涨跌幅列
        pct_change_col = None
        for col in df.columns:
            if '涨跌幅' in str(col):
                pct_change_col = col
                break

        if pct_change_col:
            plt.figure(figsize=(12, 7))

            # 绘制涨跌幅直方图
            plt.hist(df[pct_change_col], bins=30, color='green', alpha=0.7, edgecolor='black')

            # 添加均值和中位数线
            plt.axvline(df[pct_change_col].mean(), color='red', linestyle='dashed', linewidth=2,
                        label=f'均值: {df[pct_change_col].mean():.2f}%')
            plt.axvline(df[pct_change_col].median(), color='blue', linestyle='dashed', linewidth=2,
                        label=f'中位数: {df[pct_change_col].median():.2f}%')

            # 设置标题和标签
            plt.title('2023年比亚迪股票涨跌幅分布', fontsize=16, pad=20)
            plt.xlabel('涨跌幅 (%)', fontsize=12, labelpad=10)
            plt.ylabel('频数', fontsize=12, labelpad=10)

            # 设置网格线
            plt.grid(True, linestyle='--', alpha=0.3, axis='y')

            # 添加图例
            plt.legend(fontsize=10)

            plt.tight_layout()

            # 保存涨跌幅分布图
            pct_dist_path = 'd:\\1\\byd_pct_change_dist.png'
            plt.savefig(pct_dist_path, dpi=300, bbox_inches='tight')
            plt.close()
            print(f"\n涨跌幅分布图已保存至: {pct_dist_path}")

        # 绘制月平均价格对比图
        print("\n=== 绘制月平均价格对比图 ===")
        if close_col:
            # 添加月份列用于分组
            df['月份'] = df['日期'].dt.to_period('M')

            # 按月份计算平均价格
            monthly_avg = df.groupby('月份')[close_col].mean()

            # 转换period为datetime以方便绘图
            monthly_avg.index = monthly_avg.index.astype(str)

            # 创建月平均价格图
            plt.figure(figsize=(14, 7))
            bars = plt.bar(monthly_avg.index, monthly_avg.values, color='skyblue', alpha=0.7)

            # 在柱状图上添加数值标签
            for bar in bars:
                height = bar.get_height()
                plt.text(bar.get_x() + bar.get_width() / 2., height, f'{height:.2f}',
                         ha='center', va='bottom')

            # 设置标题和标签
            plt.title('2023年比亚迪股票月平均收盘价对比', fontsize=16, pad=20)
            plt.xlabel('月份', fontsize=12, labelpad=10)
            plt.ylabel('平均收盘价 (元)', fontsize=12, labelpad=10)

            # 设置网格线
            plt.grid(True, linestyle='--', alpha=0.3, axis='y')

            # 自动调整日期标签角度
            plt.xticks(rotation=45)
            plt.tight_layout()

            # 保存月平均价格图
            monthly_avg_path = 'd:\\1\\byd_monthly_avg_price.png'
            plt.savefig(monthly_avg_path, dpi=300, bbox_inches='tight')
            plt.close()
            print(f"\n月平均价格对比图已保存至: {monthly_avg_path}")
    else:
        print("未找到日期列")

    # 绘制2023年4月到2023年6月的K线图
    print("\n=== 绘制2023年4月至6月K线图 ===")

    if '日期' in df.columns:
        # 确保日期列为datetime类型
        df['日期'] = pd.to_datetime(df['日期'])

        # 筛选2023年4月到6月的数据
        mask = (df['日期'] >= '2023-04-01') & (df['日期'] <= '2023-06-30')
        df_quarter = df.loc[mask].copy()

        if len(df_quarter) > 0:
            print(f"\n筛选后数据量: {len(df_quarter)} 条记录")
            print(f"筛选后日期范围: {df_quarter['日期'].min()} 至 {df_quarter['日期'].max()}")

            # 查找OHLC列
            open_col = high_col = low_col = close_col = volume_col = None

            for col in df.columns:
                if '开盘' in str(col):
                    open_col = col
                elif '最高' in str(col):
                    high_col = col
                elif '最低' in str(col):
                    low_col = col
                elif '收盘' in str(col):
                    close_col = col
                elif '成交量' in str(col):
                    volume_col = col

            if open_col and high_col and low_col and close_col:
                print(f"\n找到K线数据列:")
                print(f"开盘价: {open_col}")
                print(f"最高价: {high_col}")
                print(f"最低价: {low_col}")
                print(f"收盘价: {close_col}")
                if volume_col:
                    print(f"成交量: {volume_col}")

                # 准备mplfinance需要的数据格式
                df_k = df_quarter.set_index('日期')
                df_k = df_k.rename(columns={
                    open_col: 'Open',
                    high_col: 'High',
                    low_col: 'Low',
                    close_col: 'Close'
                })

                # 如果有成交量，添加到数据中
                if volume_col:
                    df_k = df_k.rename(columns={volume_col: 'Volume'})

                # 计算移动平均线
                df_k['MA5'] = df_k['Close'].rolling(window=5).mean()
                df_k['MA10'] = df_k['Close'].rolling(window=10).mean()
                df_k['MA20'] = df_k['Close'].rolling(window=20).mean()

                # 定义K线图样式
                mc = mpf.make_marketcolors(
                    up='red',  # 上涨K线为红色
                    down='green',  # 下跌K线为绿色（中国习惯）
                    edge='black',  # 边框颜色
                    wick={'up': 'red', 'down': 'green'},  # 影线颜色
                    volume={'up': 'red', 'down': 'green'}  # 成交量颜色
                )

                # 设置mplfinance样式时指定字体
                s = mpf.make_mpf_style(
                    marketcolors=mc,
                    gridstyle='--',
                    figcolor='white',
                    rc={'font.family': ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC', 'Arial Unicode MS']}
                )

                # 设置额外的图表元素
                apds = [
                    mpf.make_addplot(df_k['MA5'], color='blue', width=1.0),  # 5日均线
                    mpf.make_addplot(df_k['MA10'], color='orange', width=1.0),  # 10日均线
                    mpf.make_addplot(df_k['MA20'], color='purple', width=1.0)  # 20日均线
                ]

                # 为mplfinance设置英文标题以避免中文字体问题（备选方案）
                # 使用英文标题，这样即使没有中文字体也能正常显示
                kline_path = 'd:\\1\\byd_kline_april_june_2023.png'
                mpf.plot(df_k, type='candle', style=s, title='BYD Stock K-line Chart (Apr-Jun 2023)',
                         ylabel='Price', addplot=apds, volume=volume_col is not None,
                         ylabel_lower='Volume', figsize=(16, 10),
                         savefig=dict(fname=kline_path, dpi=300, bbox_inches='tight'))

                print(f"\nK线图已保存至: {kline_path}")

                # K线图分析
                print("\n=== K线图分析 ===")

                # 1. 价格走势分析
                start_price = df_k['Close'].iloc[0]
                end_price = df_k['Close'].iloc[-1]
                price_change_pct = (end_price - start_price) / start_price * 100

                print(f"\n价格走势:")
                print(f"起始收盘价: {start_price:.2f}")
                print(f"结束收盘价: {end_price:.2f}")
                print(f"区间涨跌幅: {price_change_pct:.2f}%")

                # 2. 波动特征分析
                df_k['Daily_Range'] = df_k['High'] - df_k['Low']
                avg_range = df_k['Daily_Range'].mean()
                max_range = df_k['Daily_Range'].max()
                volatility = df_k['Close'].pct_change().std() * 100

                print(f"\n波动特征:")
                print(f"平均日波动幅度: {avg_range:.2f}")
                print(f"最大日波动幅度: {max_range:.2f}")
                print(f"日收益率标准差(波动率): {volatility:.2f}%")

                # 3. 趋势分析（基于移动平均线）
                print(f"\n趋势分析:")
                if not df_k['MA5'].isnull().all() and not df_k['MA10'].isnull().all():
                    # 计算均线斜率（简化版，用最后几天的变化率）
                    ma5_slope = (df_k['MA5'].iloc[-1] - df_k['MA5'].iloc[-5]) / df_k['MA5'].iloc[-5] * 100
                    ma10_slope = (df_k['MA10'].iloc[-1] - df_k['MA10'].iloc[-10]) / df_k['MA10'].iloc[-10] * 100

                    print(f"5日均线斜率: {ma5_slope:.2f}%")
                    print(f"10日均线斜率: {ma10_slope:.2f}%")

                    # 判断趋势
                    if ma5_slope > 1 and ma10_slope > 0.5:
                        print("短期趋势: 强势上涨")
                    elif ma5_slope > 0 and ma10_slope > 0:
                        print("短期趋势: 温和上涨")
                    elif ma5_slope < -1 and ma10_slope < -0.5:
                        print("短期趋势: 强势下跌")
                    elif ma5_slope < 0 and ma10_slope < 0:
                        print("短期趋势: 温和下跌")
                    else:
                        print("短期趋势: 震荡")

                # 4. 成交量分析
                if volume_col:
                    avg_volume = df_k['Volume'].mean()
                    max_volume = df_k['Volume'].max()
                    volume_trend = (df_k['Volume'].iloc[-5:].mean() - df_k['Volume'].iloc[:5].mean()) / df_k[
                                                                                                            'Volume'].iloc[
                                                                                                        :5].mean() * 100

                    print(f"\n成交量分析:")
                    print(f"平均成交量: {avg_volume:.0f}")
                    print(f"最大成交量: {max_volume:.0f}")
                    print(f"成交量趋势变化: {volume_trend:.2f}%")

                # 5. 关键价格点
                print(f"\n关键价格点:")
                print(f"区间最高价: {df_k['High'].max():.2f} (日期: {df_k['High'].idxmax()})")
                print(f"区间最低价: {df_k['Low'].min():.2f} (日期: {df_k['Low'].idxmin()})")
                print(f"区间平均收盘价: {df_k['Close'].mean():.2f}")

                # 6. K线形态简单统计
                bullish_candles = ((df_k['Close'] > df_k['Open'])).sum()
                bearish_candles = ((df_k['Close'] < df_k['Open'])).sum()
                doji_candles = ((df_k['Close'] == df_k['Open'])).sum()

                print(f"\nK线形态统计:")
                print(f"阳线数量: {bullish_candles}")
                print(f"阴线数量: {bearish_candles}")
                print(f"十字星数量: {doji_candles}")

                if bullish_candles > bearish_candles * 1.2:
                    print("K线形态偏向: 多头占优")
                elif bearish_candles > bullish_candles * 1.2:
                    print("K线形态偏向: 空头占优")
                else:
                    print("K线形态偏向: 多空平衡")
            else:
                print("未找到完整的K线数据列（开盘价、最高价、最低价、收盘价）")
        else:
            print("未找到2023年4月至6月的数据")
    else:
        print("未找到日期列，无法筛选数据")

    # 生成综合分析报告
    print("\n=== 综合分析报告 ===")
    print("\n1. 数据概览:")
    print(f"   - 分析期间: 2023年1月至2023年12月")
    print(f"   - 交易天数: {df.shape[0]} 天")
    print(f"   - 数据完整性: 100%（无缺失值）")

    if '日期' in df.columns and close_col:
        print("\n2. 价格表现:")
        print(f"   - 年度涨幅: {annual_return:.2f}%")
        if annual_return > 0:
            print(f"   - 表现评价: 正增长")
        elif annual_return < -20:
            print(f"   - 表现评价: 大幅下跌")
        else:
            print(f"   - 表现评价: 负增长")

    if pct_change_col:
        # 统计上涨和下跌天数
        up_days = (df[pct_change_col] > 0).sum()
        down_days = (df[pct_change_col] < 0).sum()

        print("\n3. 交易特征:")
        print(f"   - 上涨天数: {up_days} 天")
        print(f"   - 下跌天数: {down_days} 天")
        print(f"   - 上涨概率: {(up_days / df.shape[0]) * 100:.2f}%")

    print("\n4. 可视化成果:")
    print("   - 相关系数热力图: 分析变量间关系")
    print("   - 收盘价时序图: 展示价格趋势变化")
    print("   - 月平均价格对比: 月度表现对比")
    print("   - 成交量柱状图: 分析交易活跃度")
    if pct_change_col:
        print("   - 涨跌幅分布图: 风险收益特征")
    print("   - 4-6月K线图: 中期走势技术分析")

    print("\n分析完成！所有图表已保存至 d:\1 目录。")

except Exception as e:
    print(f"读取文件时出错: {e}")
    import traceback

    traceback.print_exc()  # 打印详细错误信息